API Versioning
Learn how versioning helps manage changes in an API in an orderly manner.
Introduction#
Good API designs try to maintain stability at the API specification level to minimize the need for multiple versions of the same API. Even well-constructed APIs need changes due to the evolution of requirements and/or technology. A slight alteration can either break the functionality for those who utilize the API in their applications or lead to unwanted side effects in their functionality.
API versioning is the practice of developers improving their APIs while still leaving the prior iterations functional for clients. It gives users the freedom to upgrade to new versions at their own pace, rather than forcing the update onto them, which might break their existing application. For example, popular APIs, such as the Graph API for Facebook, might be in use for billions of users, and implementing an update to the API might make the application lose its functionality.
Expecting every single user to update to the newer client version is not a reasonable expectation. So how do we manage a new version on the server-side when many clients might still be using an older version? There may come the point where a developer aims to depreciate older versions of an API, but with versioning, consumers are given time and the option to update their applications to the version they desire.
However, not all changes warrant an entirely new version to be implemented. Let's take a look at what situations and alterations merit an upgrade. First, we’ll evaluate the key principles of versioning and whether our APIs need it or not. Then, we'll highlight how to implement and maintain it.
Versioning principles#
Since API versioning is an essential part of API design, here are some best practices that should be followed while versioning:
A new API version should not break any existing clients. If several developers have adopted an API, introducing new versions could cause their applications to break. Therefore, it’s important to create new versions that don’t break the applications that are still dependent on the old versions. This may be done by simultaneously supporting the older version of the API after a newer version has been released.
The frequency of API versions should be low. A release of another version is a huge investment and commitment on both the side of the provider and the developers who use the API. The developers need to evaluate the new API and see how it will affect their current applications. At the same time, the provider's side has to supply support across multiple versions so that there can be a smooth transition to the latest version.
Backward compatible changes. If changes in an API are compatible, then we can avoid making new versions altogether (remember that backward compatibility means newer code can read what an older software version has already written). Minor changes such as adding additional query parameters do not necessarily require any changes to the client application and will continue to function in the same manner, so it doesn’t require a new API version. For instance, if a change is made to our API that still allows dependent applications to function in the same way, rolling out a new version for the change would be unnecessary and a waste of resources.
To illustrate this, let’s take a look at the slides below, which illustrate an instanceof a client making an API call to the server with mismatching versions:
1 of 4
2 of 4
3 of 4
4 of 4
Let's evaluate the four cases above:
In the first slide, both the client and server are operating on the old version, so there shouldn’t be an issue because the versions are compatible with each other.
In this scenario, the server has updated to the new version. However, if the changes are backward compatible, there shouldn’t be an issue because there will be a contingency to handle calls from clients on older versions.
With both the client and the server on the new versions, there shouldn’t be any issues, as long as the changes made in the new version don’t break the client’s application in any way.
Here, the server most likely won’t be able to handle the new API calls unless the server is forward-compatible, but this isn’t always the case.
So, servers are backward compatible with older versions of clients, but the opposite is not true.
When to version#
Versioning is important, but what are some cases where versioning is not required? This lesson discusses scenarios when versioning is required and when it should be avoided.
Let's start with an example of a mobile phone API, where the developers are now tasked with delivering the phone's model and price in its information. This restructure changes the phone's mobileinfo from a string to an object, containing both its model and its current price. If this change is implemented without versioning, the API will repeatedly crash as it tries to parse the mobileinfo, because it’s expecting a string but getting an object in return. This situation can be visualized through the illustration below:
To resolve these breaking changes, a new version has to be rolled out, or else every consumer utilizing the API in their applications will encounter these problems. While incorporating these changes, the version of the API should be embedded in the requests so that it can be routed to the correct entity, through which the users will receive the correct response.
The scenario above is just one situation where we implement versioning. The table below examines numerous scenarios and illustrates if versioning should occur in each situation.
Scenario | Versioning required? | Example |
Minor changes that don't alter functionality | No | Removal of an obsolete entity |
Backward compatible changes | No | When the new version on the server-side can process data produced by the prior version |
Altering the structure of a resource | Yes | Changing a resource from a string to an object, such as the mobile phone API above |
Renaming entities | Yes | Changing an entity from |
Performance enhancing changes that affect functionality | Yes | Breaking the API into microservices |
Let's take Twitter as an example. In August 2020, they released the Twitter API v2 for early access, which allowed faster functionality along with updated data formats. It wasn't until a year later in June 2021 that Twitter retired its standard v1.1 endpoint—a considerable amount of time after it was displaced as the primary API version.
API versioning semantic
Versioning semantics is a convention used to assign meaningful numbers to the released API, referred to as major, minor, and patch numbers. The semantic indicates backward compatibility/incompatibility and bug fixes of an API as listed below:
-
Major: The significant changes in an API that can cause incompatibility with the older version are referred to as major versioning of an API, for example, replacing the authentication method. The structural and behavioral changes in the existing features are considered major revisions of an API.
-
Minor: Adding new functionalities in an API is a minor revision. For example, adding sign-up with Google functionality in an API, keeping the existing options as it is, does not break the API functionalities and is also backward compatible with the older version.
-
Patch: Fixing bugs or making small updates in the functionality of an API is referred to as patch versioning and such fixes are also backward compatible. For example, an API returning a user’s data twice is a bug and can be fixed without altering an API’s functionality.
The number semantic can be seen in the following illustration:
In the illustration above, five indicates the 5th major version of an API in which one new functionality was added as a minor update, and ten bugs were fixed in this new minor update.
Note: Some organizations may override the guidelines mentioned above. For this reason, the guidelines are subjective (what should be a minor revision might be treated as a major release for someone else). For example, when iOS is released each year to go with a new version of the iPhone, it usually has a new major number. If we compare the number of features from one year to the next, they may differ in number and applicability.
Different versioning approaches#
There are several API versioning approaches that various companies across the world employ. We’ll take a look at four of the most popular approaches below:
Versioning with URLs: This is the most common method of versioning because it’s simple and effective. In this approach, the version information of the API is included within the URL in the form of an identifier, such as
/v1. The URL follows a strict template so that parsing the version from the URL is achievable. When the identifier changes, it’s assumed that all the resources change as well. If a new version is introduced, a different identifier would have to be used, such as/v2. This method has the most maintenance cost compared to the rest of the procedures.Versioning with HTTP headers: In this approach, the HTTP header is used to specify the version of the API to be invoked. The preferred header for this approach is the HTTP `Accept` header. This approach is favorable because it keeps the API version outside of the URL, which prevents it from being cluttered.
Versioning using host name: Another approach for versioning is to use a new host name for each version. Let's assume that we have an API at the
api.example.comendpoint. We could implement a new version with a different host name, such asgraph.example.com. This approach is only used when we have an extensive rework of an API, and we want to reroute the client requests onto a new server.
1 of 3
2 of 3
3 of 3
API version lifecycle management#
Making changes to an API requires extensive planning and testing. The consumers of our API need to be notified of any changes we might want to introduce. Here are some of the ways this can be achieved:
Announce the new version and versioning schedules.
Send emails to registered users about the changes coming soon.
Introduce warning alerts in older versions that are to be deprecated.
Define a migration period and end date for support of older versions.
Release a new API version as a beta release for a small sample of developers to get feedback and find bugs.
Launch the API while maintaining the old versions so that developers have time to migrate their code to the new version before the deprecation date.
Consider a situation where we have a gaming API. Our gaming API has a health resource as an integer value. The developers then change the health resource to include the player’s hunger state (which is a string), along with its health points on the server-side. Will this change require versioning?
Yes
No
Summary#
The versioning of APIs is an important concept when it comes to design. We should design our APIs in a manner that doesn't require too many versions, or else it becomes a hassle in the development lifecycle. Now that we've gone over the basics of versioning, let's take a look at how to evolve our API designs in the next lesson.
Quiz on API Security
Evolving an API Design